package ca.compsci.opent.compiler.semantics;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

public class SymbolTable implements Iterable<String> {
	private SymbolTable parent;
	private Hashtable<String, Symbol> symbols = new Hashtable<String, Symbol>();
	private List<SymbolTable> children = new ArrayList<SymbolTable>();
	
	public static SymbolTable newScope() {
		return new SymbolTable(null);
	}
	
	public static SymbolTable newScope(SymbolTable parent) {
		return new SymbolTable(parent);
	}
	
	private SymbolTable(SymbolTable parent) {
		this.parent = parent;
	}
	
	public SymbolTable newSubScope() {
		SymbolTable child = new SymbolTable(this);
		children.add(child);
		return child;
	}
	
	public void add(String ident, Symbol sym) {
		symbols.put(ident, sym);
	}
	
	public void remove(String ident) {
		symbols.remove(ident);
	}
	
	public Symbol getInfo(String ident) {
		Symbol sym = symbols.get(ident);
		if (sym == null) {
			if (parent == null)
				return null;
			return parent.getInfo(ident);
		} else {
			return sym;
		}
	}
	
	public SymbolTable getParent() {
		return parent;
	}
	
	public Iterator<SymbolTable> getSubScopeIterator() {
		return children.iterator();
	}
	
	public boolean isVisible(String ident) {
		if (symbols.containsKey(ident))
			return true;
		if (parent == null)
			return false;
		return parent.isVisible(ident);
	}
	
	public Iterator<String> iterator() {
		return symbols.keySet().iterator();
	}
}
